﻿using System;
using System.Collections.Generic;
using System.Text;
using Pixysoft.Framework.XSchEmA.Entity;
using Pixysoft.Framework.XSchEmA.Aspect;

namespace Pixysoft.Framework.XSchEmA.Modifier
{
    /// <summary>
    /// 处理无数据对实体对象处理，还直接操作数据库
    /// </summary>
    class RealTableModifier : ITableModifier
    {
        ISchemaCommand command = null;

        ISchemaAspect aspect = null;

        public RealTableModifier(ISchemaCommand command, ISchemaAspect aspect)
        {
            this.command = command;

            this.aspect = aspect;
        }

        /// <summary>
        /// 创建表 不支持跳过、异常抛出、其他默认
        /// </summary>
        /// <param name="databaseTo"></param>
        /// <param name="databaseFrom"></param>
        /// <param name="table"></param>
        /// <returns></returns>
        public void CreateTable(DatabaseSchema databaseTo, DatabaseSchema databaseFrom, TableSchema table)
        {
            //目前不支持sqlite的建表时的外键问题。由于外键会产生级联的建表问题，所以暂时不支持

            new TableModifier(aspect).CreateTable(databaseTo, databaseFrom, table);

            command.SQL = aspect.SqlBuilder.CreateTable(databaseTo, table);

            command.Execute();

            foreach (IndexSchema index in databaseTo.GetIndexs(table))
            {
                command.SQL = aspect.SqlBuilder.AlterTableCreateIndex(index);

                if (string.IsNullOrEmpty(command.SQL))
                    continue;

                command.Execute();
            }

            foreach (UniqueSchema unique in databaseTo.GetUniques(table))
            {
                command.SQL = aspect.SqlBuilder.AlterTableCreateConstraint(unique);

                if (string.IsNullOrEmpty(command.SQL))
                    continue;

                command.Execute();
            }

            PrimaryKeySchema pk = databaseTo.GetPrimaryKey(table);
            if (pk != null)
            {
                command.SQL = aspect.SqlBuilder.AlterTableCreateConstraint(pk);

                if (!string.IsNullOrEmpty(command.SQL))
                    command.Execute();
            }

            //CreateTableForeignKeys(database, table);
        }

        private void CreateTableForeignKeys(DatabaseSchema database, TableSchema table)
        {
            List<ForeignKeySchema> fks = new List<ForeignKeySchema>();

            foreach (ForeignKeySchema fk in database.GetBeingForeignKeys(table))
            {
                if (fks.Contains(fk))
                    continue;

                fks.Add(fk);

                command.SQL = aspect.SqlBuilder.AlterTableCreateConstraint( fk);

                if (string.IsNullOrEmpty(command.SQL))
                    continue;

                command.Execute();
            }

            foreach (ForeignKeySchema fk in database.GetForeignKeys(table))
            {
                if (fks.Contains(fk))
                    continue;

                fks.Add(fk);

                command.SQL = aspect.SqlBuilder.AlterTableCreateConstraint( fk);

                if (string.IsNullOrEmpty(command.SQL))
                    continue;

                command.Execute();
            }
        }


        /// <summary>
        /// 不支持跳过、异常抛出，其他默认
        /// </summary>
        /// <param name="database"></param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public TableSchema CreateTable(DatabaseSchema database, string tableName)
        {
            TableSchema table = new TableModifier(aspect).CreateTable(database, tableName);

            command.SQL = aspect.SqlBuilder.CreateTable(database, table);

            command.Execute();

            return table;
        }

        /// <summary>
        /// 不支持跳过 异常抛出
        /// </summary>
        /// <param name="database"></param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public void DeleteTable(DatabaseSchema database, string tableName)
        {
            TableSchema table = database.GetTable(tableName);

            if (table == null)
                throw new Exception("missing tablename");

            try
            {
                new RealColumnModifier(command, aspect).DeleteForeignKeys(database, tableName);
            }
            catch (NotSupportedException ex)
            {
                //do nothing
            }
            catch (Exception ex)
            {
                throw ex;
            }

            PrimaryKeySchema pk = database.GetPrimaryKey(table);
            if (pk != null)
            {
                command.SQL = aspect.SqlBuilder.AlterTableDropConstraint(pk);

                if (!string.IsNullOrEmpty(command.SQL))
                    command.Execute();
            }

            List<UniqueSchema> uniquelist = database.GetUniques(table);
            foreach (UniqueSchema unique in uniquelist)
            {
                command.SQL = aspect.SqlBuilder.AlterTableDropConstraint(unique);

                if (!string.IsNullOrEmpty(command.SQL))
                    command.Execute();
            }

            List<IndexSchema> indexlist = database.GetIndexs(table);
            foreach (IndexSchema index in indexlist)
            {
                command.SQL = aspect.SqlBuilder.AlterTableDropIndex(index);

                if (!string.IsNullOrEmpty(command.SQL))
                    command.Execute();
            }

            command.SQL = aspect.SqlBuilder.DropTable(tableName);

            command.Execute();
            new TableModifier(aspect).DeleteTable(database, tableName);
        }
    }
}
